import type {RouteLocationNormalized, Router, RouteRecordNormalized} from 'vue-router';
import {createRouter, createWebHashHistory, RouteRecordRaw} from 'vue-router';
import {isUrl} from '@/utils/is';
import {cloneDeep, omit} from 'lodash-es';

const modules = import.meta.glob('../views/**/*.{vue,tsx}');
/**
 * 注册一个异步组件
 * @param componentPath 例:/bpm/oa/leave/detail
 */
export const registerComponent = (componentPath: string) => {
    for (const item in modules) {
        if (item.includes(componentPath)) {
            // 使用异步组件的方式来动态加载组件
            // @ts-ignore
            return defineAsyncComponent(modules[item]);
        }
    }
};
/* Layout */
export const Layout = () => import('@/layout/Layout.vue');

export const getParentLayout = () => {
    return () =>
        new Promise((resolve) => {
            resolve({
                name: 'ParentLayout',
            });
        });
};

// 按照路由中meta下的rank等级升序来排序路由
export const ascending = (arr: any[]) => {
    arr.forEach((v) => {
        if (v?.meta?.rank === null) v.meta.rank = undefined;
        if (v?.meta?.rank === 0) {
            if (v.name !== 'home' && v.path !== '/') {
                console.warn('rank only the home page can be 0');
            }
        }
    });
    return arr.sort((a: { meta: { rank: number } }, b: { meta: { rank: number } }) => {
        return a?.meta?.rank - b?.meta?.rank;
    });
};

export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormalized => {
    if (!route) return route;
    const {matched, ...opt} = route;
    return {
        ...opt,
        matched: (matched
            ? matched.map((item) => ({
                meta: item.meta,
                name: item.name,
                path: item.path,
            }))
            : undefined) as RouteRecordNormalized[],
    };
};

// 后端控制路由生成
export const generateRoute = (routes: AppCustomRouteRecordRaw[]): AppRouteRecordRaw[] => {
    const res: AppRouteRecordRaw[] = [];
    // 获取所有视图组件key
    const modulesRoutesKeys = Object.keys(modules);

    for (const route of routes) {
        const meta = {
            title: route.name,
            icon: route.icon,
            hidden: !route.visible,
            noCache: !route.keepAlive,
            alwaysShow:
                route.children &&
                route.children.length === 1 &&
                (route.alwaysShow !== undefined ? route.alwaysShow : true),
        };
        // 路由地址转首字母大写驼峰，作为路由名称，适配keepAlive
        let data: AppRouteRecordRaw = {
            path: route.path,
            name:
                route.componentName && route.componentName.length > 0
                    ? route.componentName
                    : toCamelCase(route.path, true),
            redirect: route.redirect,
            meta: meta,
        };
        //处理顶级非目录路由
        if (!route.children && route.parentId == 0 && route.component) {
            data.component = Layout;
            data.meta = {};
            data.name = toCamelCase(route.path, true) + 'Parent';
            data.redirect = '';
            meta.alwaysShow = true;
            const childrenData: AppRouteRecordRaw = {
                path: '',
                name: route.componentName && route.componentName.length > 0
                    ? route.componentName
                    : toCamelCase(route.path, true),
                redirect: route.redirect,
                meta: meta,
            };
            const index = route?.component
                ? modulesRoutesKeys.findIndex((ev) => ev.includes(route.component))
                : modulesRoutesKeys.findIndex((ev) => ev.includes(route.path));
            childrenData.component = modules[modulesRoutesKeys[index]];
            data.children = [childrenData];
        } else {
            // 目录
            if (route.children) {
                data.component = Layout;
                data.redirect = getRedirect(route.path, route.children);
                // 外链
            } else if (isUrl(route.path)) {
                data = {
                    path: '/external-link',
                    component: Layout,
                    meta: {
                        name: route.name,
                    },
                    children: [data],
                } as AppRouteRecordRaw;
                // 菜单
            } else {
                // 对后端传component组件路径和不传做兼容（如果后端传component组件路径，那么path可以随便写，如果不传，component组件路径会根path保持一致）
                const index = route?.component
                    ? modulesRoutesKeys.findIndex((ev) => ev.includes(route.component))
                    : modulesRoutesKeys.findIndex((ev) => ev.includes(route.path));
                data.component = modules[modulesRoutesKeys[index]];
            }
            if (route.children) {
                data.children = generateRoute(route.children);
            }
        }
        res.push(data as AppRouteRecordRaw);
    }
    return res;
};
export const getRedirect = (parentPath: string, children: AppCustomRouteRecordRaw[]) => {
    if (!children || children.length == 0) {
        return parentPath;
    }
    const path = generateRoutePath(parentPath, children[0].path);
    // 递归子节点
    if (children[0].children) return getRedirect(path, children[0].children);
};
const generateRoutePath = (parentPath: string, path: string) => {
    if (parentPath.endsWith('/')) {
        parentPath = parentPath.slice(0, -1); // 移除默认的 /
    }
    if (!path.startsWith('/')) {
        path = '/' + path;
    }
    return parentPath + path;
};
export const pathResolve = (parentPath: string, path: string) => {
    if (isUrl(path)) return path;
    const childPath = path.startsWith('/') || !path ? path : `/${path}`;
    return `${parentPath}${childPath}`.replace(/\/\//g, '/');
};

// 路由降级
export const flatMultiLevelRoutes = (routes: AppRouteRecordRaw[]) => {
    const modules: AppRouteRecordRaw[] = cloneDeep(routes);
    for (let index = 0; index < modules.length; index++) {
        const route = modules[index];
        if (!isMultipleRoute(route)) {
            continue;
        }
        promoteRouteLevel(route);
    }
    return modules;
};

// 层级是否大于2
const isMultipleRoute = (route: AppRouteRecordRaw) => {
    if (!route || !Reflect.has(route, 'children') || !route.children?.length) {
        return false;
    }

    const children = route.children;

    let flag = false;
    for (let index = 0; index < children.length; index++) {
        const child = children[index];
        if (child.children?.length) {
            flag = true;
            break;
        }
    }
    return flag;
};

// 生成二级路由
const promoteRouteLevel = (route: AppRouteRecordRaw) => {
    let router: Router | null = createRouter({
        routes: [route as RouteRecordRaw],
        history: createWebHashHistory(),
    });

    const routes = router.getRoutes();
    addToChildren(routes, route.children || [], route);
    router = null;

    route.children = route.children?.map((item) => omit(item, 'children'));
};

// 添加所有子菜单
const addToChildren = (
    routes: RouteRecordNormalized[],
    children: AppRouteRecordRaw[],
    routeModule: AppRouteRecordRaw,
) => {
    for (let index = 0; index < children.length; index++) {
        const child = children[index];
        const route = routes.find((item) => item.name === child.name);
        if (!route) {
            continue;
        }
        routeModule.children = routeModule.children || [];
        if (!routeModule.children.find((item) => item.name === route.name)) {
            routeModule.children?.push(route as unknown as AppRouteRecordRaw);
        }
        if (child.children?.length) {
            addToChildren(routes, child.children, routeModule);
        }
    }
};
const toCamelCase = (str: string, upperCaseFirst: boolean) => {
    str = (str || '')
    .replace(/-(.)/g, function (group1: string) {
        return group1.toUpperCase();
    })
    .replaceAll('-', '');

    if (upperCaseFirst && str) {
        str = str.charAt(0).toUpperCase() + str.slice(1);
    }

    return str;
};
